package com.nulldev.util.web.YouTubeExtractor.extractors;

import java.net.Proxy;
import java.util.List;
import java.util.Map;

import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.VariableAPI.MathUtil;
import com.nulldev.util.data.Arrays.maps.FastMaps;
import com.nulldev.util.languages.json.uniapi.UniJsonValue;
import com.nulldev.util.manage.MarkedForRemoval;
import com.nulldev.util.web.YouTubeExtractor.YoutubeExtractionOptions;
import com.nulldev.util.web.YouTubeExtractor.Qtraxtor.ExtractedSet;
import com.nulldev.util.web.YouTubeExtractor.Qtraxtor.Qtraxtor;
import com.nulldev.util.web.YouTubeExtractor.extractors.util.YTIAPIClientType;

public interface IYouTubeExtractorConstants {

	/* Misc. */

	/**
	 * Ignore these statues within trailer detection
	 */
	public static final String[] NON_TRAILER_PLAYABILITY_STATUSES = new String[]
		{ "OK", "LOGIN_REQUIRED", "CONTENT_CHECK_REQUIRED", "LIVE_STREAM_OFFLINE", };

	/**
	 * Allow these statuses overall within the internal code of an extractor
	 */
	public static final String[] ALLOWED_PLAYABILITY_STATUSES = new String[]
		{ "OK", "LIVE_STREAM_OFFLINE", };

	public static final int OUTPUT_LIST_DEFAULT_SIZE = 24;

	/* Core */

	public static final String MAP_TYPE_VIDEO_ID = "videoID";
	public static final Class<?> MAP_VALUE_VIDEO_ID = String.class;

	/* Pre 2.2 compat. */

	public static final String MAP_TYPE_EXTRA_ARGS_COMPAT = "extraArgs";
	public static final Class<?> MAP_VALUE_EXTRA_ARGS_COMPAT = String.class;

	public static final String MAP_TYPE_FORCE_ENGLISH_LANG_COMPAT = "hl-english-force";
	public static final Class<?> MAP_VALUE_FORCE_ENGLISH_LANG_COMPAT = boolean.class;

	public static final String MAP_TYPE_ENFORCE_PRIVACY_MODE_COMPAT = "compat-enforce-privacy-mode";
	public static final Class<?> MAP_VALUE_ENFORCE_PRIVACY_MODE_COMPAT = boolean.class;

	public static final String MAP_TYPE_DISABLE_CONSENT_COOKIE_COMPAT = "compat-disable-consent-cookie";
	public static final Class<?> MAP_VALUE_DISABLE_CONSENT_COOKIE_COMPAT = boolean.class;

	public static final String MAP_TYPE_SEND_FAKE_COOKIES_COMPAT = "send-fake-cookies-compat";
	public static final Class<?> MAP_VALUE_SEND_FAKE_COOKIES_COMPAT = boolean.class;

	public static final String MAP_TYPE_EMULATE_INSECURE_PROXY_COMPAT = "compat-emulate-insecure-proxy";
	public static final Class<?> MAP_VALUE_EMULATE_INSECURE_PROXY_COMPAT = boolean.class;

	/* 2.2 arguments */

	public static final String MAP_TYPE_PROXY = "proxy";
	public static final Class<?> MAP_VALUE_PROXY = Proxy.class;

	public static final String MAP_TYPE_PLAYLIST_STR = "playlist";
	public static final Class<?> MAP_VALUE_PLAYLIST_STR = String.class;

	public static final String MAP_TYPE_PLAYLIST_INDEX = "playlist-index";
	public static final Class<?> MAP_VALUE_PLAYLIST_INDEX = int.class;

	public static final String MAP_TYPE_SEND_X_GOOG_KEY = "send-x-goog-key";
	public static final Class<?> MAP_VALUE_SEND_X_GOOG_KEY = boolean.class;

	public static final String MAP_TYPE_ENABLE_CLARIFICATIONS = "enable-political-pandering";
	public static final Class<?> MAP_VALUE_ENABLE_CLARIFICATIONS = boolean.class;

	public static final String MAP_TYPE_ENABLE_LATE_EXTRACTIONS = "enable-late-extractions";
	public static final Class<?> MAP_VALUE_ENABLE_LATE_EXTRACTIONS = boolean.class;

	public static final String MAP_TYPE_ENABLE_EXPERIMENTAL_FEATURES = "enable-upcoming-features";
	public static final Class<?> MAP_VALUE_ENABLE_EXPERIMENTAL_FEATURES = boolean.class;

	public static final String MAP_TYPE_ENABLE_CONTROVERSY_BYPASS = "enable-controversy-bypass";
	public static final Class<?> MAP_VALUE_ENABLE_CONTROVERSY_BYPASS = boolean.class;

	public static final String MAP_TYPE_ENABLE_VERIFIED_SPOOFING = "enable-verified-spoofing";
	public static final Class<?> MAP_VALUE_ENABLE_VERIFIED_SPOOFING = boolean.class;

	public static final String MAP_TYPE_ENABLE_DEBUG_API_RESPONSE_PRINT = "debug-print-api-response";
	public static final Class<?> MAP_VALUE_ENABLE_DEBUG_API_RESPONSE_PRINT = boolean.class;

	public static final String MAP_TYPE_ENABLE_DEBUG_FULL_RESPONSE_PRINT = "debug-print-full-response";
	public static final Class<?> MAP_VALUE_ENABLE_DEBUG_FULL_RESPONSE_PRINT = boolean.class;

	public static final String MAP_TYPE_HAS_FALLEN_BACK = "--has-fallen-back";
	public static final Class<?> MAP_VALUE_HAS_FALLEN_BACK = boolean.class;

	public static final String MAP_TYPE_FALLBACK_LAYER = "--fallback-layer";
	public static final Class<?> MAP_VALUE_FALLBACK_LAYER = int.class;

	public static final String MAP_TYPE_SOLVED_SAPISID_HASH = "--solved-sapi-hash";
	public static final Class<?> MAP_VALUE_SOLVED_SAPISID_HASH = String.class;

	public static final String MAP_TYPE_SOLVED_ID_TOKEN = "--solved-id-token";
	public static final Class<?> MAP_VALUE_SOLVED_ID_TOKEN = String.class;

	public static final String MAP_TYPE_PASSTHROUGH_COOKIES = "--passthrough-cookies";
	public static final Class<?> MAP_VALUE_PASSTHROUGH_COOKIES = String.class;

	public static final String MAP_TYPE_USE_CLIENT_TYPE = "ytiapi-use-client-type";
	public static final Class<?> MAP_VALUE_USE_CLIENT_TYPE = YTIAPIClientType.class;

	public static final String MAP_TYPE_USE_EXPERIMENTAL_BACKEND_FLAG = "ytiapi-use-staging-backend";
	public static final Class<?> MAP_VALUE_USE_EXPERIMENTAL_BACKEND_FLAG = boolean.class;

	public static final String MAP_TYPE_UTC_TIMEZONE_OFFSET = "utc-timezone-offset";
	public static final Class<?> MAP_VALUE_UTC_TIMEZONE_OFFSET = int.class;

	public static final String MAP_TYPE_DISABLE_V8_DECIPHERING = "disable-v8-cipher";
	public static final Class<?> MAP_VALUE_DISABLE_V8_DECIPHERING = boolean.class;

	public static final String MAP_TYPE_DISABLE_V9_DECIPHERING = "disable-v9-cipher";
	public static final Class<?> MAP_VALUE_DISABLE_V9_DECIPHERING = boolean.class;

	public static final String MAP_TYPE_YT_OFFICIAL_API_KEY = "yt-official-api-key";
	public static final Class<?> MAP_VALUE_YT_OFFICIAL_API_KEY = String.class;

	public static final String MAP_TYPE_USE_BACKEND_PROXY = "backend-use-proxy";
	public static final Class<?> MAP_VALUE_USE_BACKEND_PROXY = boolean.class;

	public static final String MAP_TYPE_LIVESTREAMS_KEEP_RAW_STREAMS = "livestreams-keep-raw-streams";
	public static final Class<?> MAP_VALUE_LIVESTREAMS_KEEP_RAW_STREAMS = boolean.class;

	public static final String MAP_TYPE_DEBUG_OVERRIDE_SECOND_RESPONSE = "debug-override-second-response";
	public static final Class<?> MAP_VALUE_DEBUG_OVERRIDE_SECOND_RESPONSE = UniJsonValue.class;

	public static final String MAP_TYPE_HEATMAP_DISABLE_PRIORITY_POINT = "heatmap-disable-priority-point";
	public static final Class<?> MAP_VALUE_HEATMAP_DISABLE_PRIORITY_POINT = boolean.class;

	public static final String MAP_TYPE_ENABLE_ADVERTISING_METADATA_EXTRACTION = "enable-ad-metadata-extraction";
	public static final Class<?> MAP_VALUE_ENABLE_ADVERTISING_METADATA_EXTRACTION = boolean.class;

	/* Check Map */

	public static final Map<String, Class<?>> ARGUMENT_CLASSES = FastMaps.fixedUniMap(new Object[][]
		{
				{ MAP_TYPE_VIDEO_ID, MAP_VALUE_VIDEO_ID },

				{ MAP_TYPE_EXTRA_ARGS_COMPAT, MAP_VALUE_EXTRA_ARGS_COMPAT },
				{ MAP_TYPE_PLAYLIST_STR, MAP_VALUE_PLAYLIST_STR },
				{ MAP_TYPE_PLAYLIST_INDEX, MAP_VALUE_PLAYLIST_INDEX },

				{ MAP_TYPE_ENABLE_LATE_EXTRACTIONS, MAP_VALUE_ENABLE_LATE_EXTRACTIONS },
				{ MAP_TYPE_UTC_TIMEZONE_OFFSET, MAP_VALUE_UTC_TIMEZONE_OFFSET },
				{ MAP_TYPE_HAS_FALLEN_BACK, MAP_VALUE_HAS_FALLEN_BACK },
				{ MAP_TYPE_ENABLE_VERIFIED_SPOOFING, MAP_VALUE_ENABLE_VERIFIED_SPOOFING },
				{ MAP_TYPE_PROXY, MAP_VALUE_PROXY },
				{ MAP_TYPE_SOLVED_SAPISID_HASH, MAP_VALUE_SOLVED_SAPISID_HASH },
				{ MAP_TYPE_SOLVED_ID_TOKEN, MAP_VALUE_SOLVED_ID_TOKEN },
				{ MAP_TYPE_PLAYLIST_STR, MAP_VALUE_PLAYLIST_STR },
				{ MAP_TYPE_SEND_X_GOOG_KEY, MAP_VALUE_SEND_X_GOOG_KEY },
				{ MAP_TYPE_USE_CLIENT_TYPE, MAP_VALUE_USE_CLIENT_TYPE },
				{ MAP_TYPE_USE_EXPERIMENTAL_BACKEND_FLAG, MAP_VALUE_USE_EXPERIMENTAL_BACKEND_FLAG },
				{ MAP_TYPE_FALLBACK_LAYER, MAP_VALUE_FALLBACK_LAYER },
				{ MAP_TYPE_DISABLE_V8_DECIPHERING, MAP_VALUE_DISABLE_V8_DECIPHERING },
				{ MAP_TYPE_DISABLE_V9_DECIPHERING, MAP_VALUE_DISABLE_V9_DECIPHERING },
				{ MAP_TYPE_YT_OFFICIAL_API_KEY, MAP_VALUE_YT_OFFICIAL_API_KEY },
				{ MAP_TYPE_USE_BACKEND_PROXY, MAP_VALUE_USE_BACKEND_PROXY },
				{ MAP_TYPE_LIVESTREAMS_KEEP_RAW_STREAMS, MAP_VALUE_LIVESTREAMS_KEEP_RAW_STREAMS },
				{ MAP_TYPE_HEATMAP_DISABLE_PRIORITY_POINT, MAP_VALUE_HEATMAP_DISABLE_PRIORITY_POINT },
				{ MAP_TYPE_ENABLE_ADVERTISING_METADATA_EXTRACTION, MAP_VALUE_ENABLE_ADVERTISING_METADATA_EXTRACTION },

				{ MAP_TYPE_DEBUG_OVERRIDE_SECOND_RESPONSE, MAP_VALUE_DEBUG_OVERRIDE_SECOND_RESPONSE } });

	/* Functions */

	@SuppressWarnings("deprecation")
	@MarkedForRemoval(reason = "Compatibility function for legacy ABI users.", plannedRemovalWhen = "2.2.10 or 2.3")
	public static Map<String, Object> convertFromLegacy(String videoID, String extraArgs, YoutubeExtractionOptions... options) {
		final Map<String, Object> map = FastMaps.uniMap(new Object[][]
			{
					{ MAP_TYPE_VIDEO_ID, videoID } });
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.NO_FALLBACK))
			map.put(MAP_TYPE_HAS_FALLEN_BACK, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.SEND_X_GOOG_API_KEY))
			map.put(MAP_TYPE_SEND_X_GOOG_KEY, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.ALLOW_LATE_EXTRACTIONS))
			map.put(MAP_TYPE_ENABLE_LATE_EXTRACTIONS, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.ENABLE_POLTICIAL_PANDERING))
			map.put(MAP_TYPE_ENABLE_CLARIFICATIONS, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.ADD_CONTROVERSY_BYPASS))
			map.put(MAP_TYPE_ENABLE_CONTROVERSY_BYPASS, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.ENABLE_UPCOMING_FEATURES))
			map.put(MAP_TYPE_ENABLE_EXPERIMENTAL_FEATURES, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.DEBUG_PRINT_API_RESPONSE))
			map.put(MAP_TYPE_ENABLE_DEBUG_API_RESPONSE_PRINT, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.EMULATE_INSECURE_PROXY))
			map.put(MAP_TYPE_EMULATE_INSECURE_PROXY_COMPAT, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.DISABLE_SEND_CONSENT_COOKIE))
			map.put(MAP_TYPE_DISABLE_CONSENT_COOKIE_COMPAT, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.SEND_FAKE_COOKIE_DATA))
			map.put(MAP_TYPE_SEND_FAKE_COOKIES_COMPAT, true);
		if (ArrayUtils.contains(options, YoutubeExtractionOptions.ENFORCE_PRIVACY_MODE))
			map.put(MAP_TYPE_ENFORCE_PRIVACY_MODE_COMPAT, true);
		if (extraArgs != null && !extraArgs.isEmpty()) {
			final List<ExtractedSet> o = Qtraxtor.get(extraArgs);
			for (final ExtractedSet s : o) {
				if (s.get().containsKey("list")) {
					map.putIfAbsent(MAP_TYPE_PLAYLIST_STR, s.get().get("list"));
				} else if (s.get().containsKey("index")) {
					final int index = MathUtil.safeParseInt(s.get().get("index"), -1);
					map.putIfAbsent(MAP_TYPE_PLAYLIST_INDEX, index);
				}
			}
		}
		return map;
	}

	/* Feature Flags */

	public static final int FLAG_NOT_SUPPORTED = -1;
	public static final int FLAG_FALSE = 0;
	public static final int FLAG_TRUE = 1;

	public static final int FLAG_EXTRACTOR_SUPPORTS_AGE_GATE = 2;
	public static final int FLAG_EXTRACTOR_SUPPORTS_LIVESTREAMS = 3;
	public static final int FLAG_EXTRACTOR_SUPPORTS_LIVESTREAM_CHAT = 4;
	public static final int FLAG_EXTRACTOR_SUPPORTS_LATE_EXTRACTION = 5;
	public static final int FLAG_EXTRACTOR_SUPPORTS_SEGMENTED_EXTRACTION = 6;
	public static final int FLAG_EXTRACTOR_SUPPORTS_ABI_2_2 = 7;
	public static final int FLAG_EXTRACTOR_GET_SUPPORTED_ABI = 8;
	public static final int FLAG_EXTRACTOR_SUPPORTS_HEATMAPS = 9;

	/* Misc values */

	public static final String[] DESCRIPTION_REPLACEMENTS_INPUT =
		{ "\r\n", "\n", "%3B" };
	public static final String[] DESCRIPTION_REPLACEMENTS_OUTPUT =
		{ "<br>", "<br>", ";" };
}
